#pragma once
#include <iostream>
#include <string>
#include "Commn.hpp"
#include <vector>
#include <sstream>
#include <unordered_map>
#include <fstream>
#include "Log.hpp"

using namespace LogModule;

const std::string Sep = "\r\n";
const std::string BankLine = Sep;
const std::string LineSep = " ";
const std::string HeaderSep = ": ";
const std::string HomePage = "wwwroot";
const std::string FirstPage = "index.html";
const std::string _404Page = "wwwroot/404.html";

class Request
{
public:
    Request()
    {
    }
    ~Request() {}
    void ParseHeader(std::string& in_str)
    {
        std::string line;
        while (true)
        {
            std::string k,v;
            bool r = ParseOneLine(&line, in_str,Sep);
            if (r && !line.empty()){
                //正常报文
                SplitHeader(line,&k,&v,HeaderSep);
                _headerkv.insert(std::make_pair(k,v));                
                _req_header.push_back(line + Sep);
            }
            else if(r && line.empty()){
                _blankLine = BankLine;
                break;
            }
            else //没有空行
            {
                return;
            }
        }
    }
    void Deserialize(std::string &in_str)
    {
        if (ParseOneLine(&_reqLine, in_str,Sep))
        {
            ParseReqLine();
            ParseHeader(in_str);
        }
        _body = in_str;

        if (_method == "GET")
        {
            auto pos = _url.find("?");
            if (pos != std::string::npos)
            {
                _path = _url.substr(0,pos);
                _args = _url.substr(pos+1);
                _execv = true;
            }
        }
        else if(_method == "POST")
        {
            _path = _url;
            _execv = true;
            _args = _body;
        }
        
        LOG(LogLevel::INFO) << "------------------------------------------------------";
        LOG(LogLevel::DEBUG) << " url: " << _url << " Path: " << _path << " Args: " << _args;
        LOG(LogLevel::INFO) << "------------------------------------------------------";
    }
    //const Request* req
    std::string Path() const {return _path;} //Request* const 
    std::string Args()const { return _args;}
    bool HasArgs(){return _execv;}
    void SplitHeader(std::string& str,std::string*k,std::string*v,const std::string& sep)
    {
        auto pos = str.find(sep);
        if (pos == std::string::npos) return;
        *k = str.substr(0,pos);
        *v = str.substr(pos+sep.size());
    }

    void Print()
    {
        std::cout << "_method: " << _method << std::endl;
        std::cout << "_url: " << _url << std::endl;
        std::cout << "_edition: " << _edition << std::endl;

        std::cout << _reqLine;
        for (auto &x : _req_header)
            std::cout << x;
        // for(auto& line : _headerkv)
        // {
        //     std::cout << line.first << " # " << line.second << std::endl;
        // }
        std::cout << _blankLine;
        std::cout << "_body: " << _body << std::endl;
    }
    std::string GetContent(const std::string& url) const 
    {
        // //暂时的版本
        // std::ifstream in(_url.c_str());
        // if (!in.is_open()) return std::string(); //文件不存在的话直接返回空
        // std::string line;
        // std::string content;
        // while(std::getline(in,line))
        // {
        //     content += line;
        // }
        // return content;
        std::string content;
        std::ifstream in(url.c_str(),std::ios::binary);
        if (!in.is_open()) return std::string(); //文件不存在的话直接返回空
        in.seekg(0,in.end);
        int fullsize = in.tellg();
        content.resize(fullsize);
        in.seekg(0,in.beg);
        in.read((char*)content.c_str(),fullsize);
        in.close();
        return content;
    }
    std::string Url() { return _url;}
    void SetUrl(const std::string& url) {_url = url;}
private:
    inline void ParseReqLine()
    {
        std::stringstream ss(_reqLine);
        ss >> _method >> _url >> _edition;
        // _url = HomePage + _url;
        // LOG(LogLevel::DEBUG) << "url: " << _url;
    }
    std::string _reqLine;
    std::vector<std::string> _req_header;
    std::string _blankLine;
    std::string _body;
    std::unordered_map<std::string,std::string> _headerkv;

    std::string _method;
    std::string _url;
    std::string _edition;
    bool _execv = false;
    std::string _path;
    std::string _args;
};




class Response
{
public:
    Response() 
        :_version("HTTP/1.0")
        {}
    ~Response() {}

    void Build(Request& req)
    {

        std::string url = HomePage + req.Url();
        LOG(LogLevel::DEBUG) << "当前的url: " << url;
        if (url.back() == '/') url += FirstPage; //访问目录的时候，直接定位默认首页
        _body = req.GetContent(url);
        if (_body.empty()) //文件不存在
        {
            _status = 404;
            // req.SetUrl(_404Page);
            // url = _404Page;
            _body = req.GetContent(_404Page);
            // LOG(LogLevel::DEBUG) << "报错修正后的url: " << req.Url();
        }
        else 
        {
            _status = 200;
        }
        LOG(LogLevel::INFO) << "之后url: "<< url;

        _status_desc = Status2Desc();

        std::string mime_type;
        if (!_body.empty()) //_body不为空
        {
            SetHeader("Content-Length",std::to_string(_body.size()));

        }
        mime_type = suf2type(sufixinfo(req.Url()));
        SetHeader("Content-Type",mime_type);



    }
    void SetBody(std::string&body)  
    {
        _body = body;
    }
    void SetCode(int code)  
    {
        _status = code;
        _status_desc = Status2Desc();
    }
    void SetHeader(const std::string& k,const std::string& v)  
    {
        _headerkv.insert(std::make_pair(k,v));
    }
    void Serialize(std::string* out_str)
    {
        _reqLine = _version + LineSep + std::to_string(_status) + LineSep + _status_desc + Sep;
        *out_str = _reqLine;
        for (auto& line : _headerkv)
        {
            std::string str;
            GetReqHeader(&str,line.first,line.second,HeaderSep);
            _req_header.push_back(str + Sep); //添加\r\n
        }
                
        for (auto& line : _req_header)
        {
            *out_str += line;
        }
        _blankLine = BankLine;
        *out_str += _blankLine;
        *out_str += _body;
    }
    void GetReqHeader(std::string* out,const std::string&k,const std::string&v,const std::string& sep)
    {
        *out = k + sep + v;
    }
    std::string sufixinfo(const std::string& url)
    {
        auto pos = url.rfind(".");
        if (pos == std::string::npos) return std::string();
        return url.substr(pos);
    }
    std::string suf2type(const std::string&s)
    {
        if (s == ".jpj") return "application/x-jpg";
        else if(s == ".html") return "text/html";
        else return "text/html";
    }
private:

    std::string Status2Desc()
    {
        switch(_status)
        {
            case 200:
                return "OK";
            case 404:
                return "Not Found";
            case 301:
                return "Moved Permanently";
            case 302:
                return "Found";
            default:
                return "OK";
        }
        return "OK";
    }
private:
    std::string _reqLine;
    std::vector<std::string> _req_header;
    std::string _blankLine;
    std::string _body;
    
    std::unordered_map<std::string,std::string> _headerkv;
    std::string _version;
    int _status;
    std::string _status_desc;
};